package com.bilibili.liveremind.module.biliwss;

import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bilibili.liveremind.module.vo.AuthPackVo;
import org.apache.commons.compress.compressors.brotli.BrotliCompressorInputStream;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.io.*;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class WebsocketListener extends WebSocketClient {

    private final AuthPackVo authPackVo;

    public WebsocketListener(URI serverUri,AuthPackVo authPackVo) {
        super(serverUri);
        this.authPackVo = authPackVo;
        System.out.println("WebsocketListener");
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        System.out.println("--onOpen--");
        byte[] bytes = new byte[1024];
        try {
            bytes = generateAuthPack();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //鉴权协议包
        super.send(bytes);

        //心跳包
        //每30秒发送心跳包
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(() -> {
            try {
                super.send(generateHeartBeatPack());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }, 0, 30, TimeUnit.SECONDS);


    }

    @Override
    public void onMessage(String s) {

    }

    @Override
    public void onMessage(ByteBuffer message) {
        System.out.println("--onMessage--");
        unpack(message);
    }

    @Override
    public void onClose(int i, String s, boolean b) {
        System.out.println("--onClose--");
    }

    @Override
    public void onError(Exception e) {
            System.out.println("--onClose--"+e.getMessage());
    }


    /**
     * 封包
     * @param jsonStr 数据
     * @param code 协议包类型
     * @return
     * @throws IOException
     */
    public static byte[] pack(String jsonStr, short code) throws IOException {
        byte[] contentBytes = new byte[0];
        if(7 == code){
            contentBytes = jsonStr.getBytes();
        }
        try(ByteArrayOutputStream data = new ByteArrayOutputStream();
            DataOutputStream stream = new DataOutputStream(data)){
            stream.writeInt(contentBytes.length + 16);//封包总大小
            stream.writeShort(16);//头部长度 header的长度，固定为16
            stream.writeShort(1);
            stream.writeInt(code);//操作码（封包类型）
            stream.writeInt(1);//sequence，可以取常数1 .保留字段，可以忽略。
            if(7 == code){
                stream.writeBytes(jsonStr);
            }
            return data.toByteArray();
        }
    }

    /**
     * 生成认证包-用于非官方开放API
     * @return
     */
    public byte[] generateAuthPack() throws IOException {
        JSONObject jo = new JSONObject();
        jo.put("uid", authPackVo.getUid());
        jo.put("roomid", authPackVo.getRoomid());
        jo.put("protover", authPackVo.getProtover());
        jo.put("buvid", authPackVo.getBuvid());
        jo.put("platform", authPackVo.getPlatform());
        jo.put("type", authPackVo.getType());
        jo.put("key", authPackVo.getKey());
        return pack(jo.toString(), (short) 7);
    }

    /**
     * 生成心跳包
     * @return
     */
    public static byte[] generateHeartBeatPack() throws IOException {
        return pack(null, (short) 2);
    }

    public static void unpack(ByteBuffer byteBuffer){
        int packageLen = byteBuffer.getInt();
        short headLength = byteBuffer.getShort();
        short protVer = byteBuffer.getShort();
        System.out.println("protVer----"+protVer);
        int optCode = byteBuffer.getInt();
        int sequence = byteBuffer.getInt();
        if(3 == optCode){
            System.out.println("这是服务器心跳回复");
        }
        byte[] contentBytes = new byte[packageLen - headLength];
        byteBuffer.get(contentBytes);
        //如果是zip包就进行解包
        if(2 == protVer){
            unpack(ByteBuffer.wrap(ZipUtil.unZlib(contentBytes)));
            return;
        }

        String content = new String(contentBytes, StandardCharsets.UTF_8);
        if(8 == optCode){
            //返回{"code":0}表示成功
            System.out.println("这是鉴权回复："+content);
        }
        //真正的弹幕消息
        if(5 == optCode){
            //System.out.println("真正的弹幕消息："+content);
            //todo 自定义处理
            //brotli解压 用户发送弹幕需要解压
            if (3 == protVer){
                // 假设你有一个Brotli压缩的byte数组
                byte[] compressedData = contentBytes;
                try {
                    // 创建一个ByteArrayInputStream对象
                    InputStream inputStream = new ByteArrayInputStream(compressedData);

                    // 创建一个BrotliCompressorInputStream对象
                    BrotliCompressorInputStream brotliInputStream = new BrotliCompressorInputStream(inputStream);

                    // 读取解压后的文本
                    byte[] buffer = new byte[1024];
                    StringBuilder decompressedText = new StringBuilder();
                    int len;
                    while ((len = brotliInputStream.read(buffer)) != -1) {
                        decompressedText.append(new String(buffer, 0, len, StandardCharsets.UTF_8));
                    }
                    // 关闭流
                    brotliInputStream.close();
                    // 输出解压后的文本
                    String data = decompressedText.toString();
                    //截取头部16字节得到真正的弹幕
                    content = data.substring(16);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            JSONObject contentJson = JSONUtil.parseObj(content);
            System.out.println(contentJson);
            String cmd = contentJson.getStr("cmd");
            System.out.println("cmd-----:"+cmd);
            //用户发送的弹幕
            if ("DANMU_MSG".equals(cmd)){
                JSONArray infoJson = contentJson.getJSONArray("info");
                //弹幕内容
                String danmuContent = infoJson.getStr(1);
                //用户名
                JSONArray nameJson = infoJson.getJSONArray(2);
                String name = nameJson.getStr(1);
                System.out.println("name:"+name+">>>>>content:"+danmuContent);
            }else if ("ONLINE_RANK_COUNT".equals(cmd)){
                //高能用户数量 {"cmd":"ONLINE_RANK_COUNT","data":{"count":13}}
                JSONObject highUserCountJson  = contentJson.getJSONObject("data");
                Integer highUserCount = highUserCountJson.getInt("count");
                Integer highUserOnlineCount = highUserCountJson.getInt("online_count");
                System.out.println("高能用户数量："+highUserCount+">>>>高能用户数量："+highUserOnlineCount);
            }else if ("LIKE_INFO_V3_CLICK".equals(cmd)){
                //用户点赞 {"cmd":"LIKE_INFO_V3_CLICK","data":{"contribution_info":{"grade":0},"dmscore":68,"fans_medal":{"anchor_roomid":0,"guard_level":3,"icon_id":0,"is_lighted":1,"medal_color":1725515,"medal_color_border":6809855,"medal_color_end":5414290,"medal_color_start":1725515,"medal_level":23,"medal_name":"睡叭","score":50007380,"special":"","target_id":21500070},"group_medal":null,"identities":[6,3,1],"is_mystery":false,"like_icon":"https://i0.hdslb.com/bfs/live/23678e3d90402bea6a65251b3e728044c21b1f0f.png","like_text":"为主播点赞了","msg_type":6,"show_area":0,"uid":102076113,"uinfo":{"base":{"face":"https://i0.hdslb.com/bfs/face/fb83fe3f28cba8d5fbc5b13ef925150cad43b579.jpg","is_mystery":false,"name":"孤陌成影","name_color":0,"name_color_str":"#00D1F1","official_info":{"desc":"","role":0,"title":"","type":-1},"origin_info":{"face":"https://i0.hdslb.com/bfs/face/fb83fe3f28cba8d5fbc5b13ef925150cad43b579.jpg","name":"孤陌成影"},"risk_ctrl_info":null},"guard":{"expired_str":"2024-03-09 23:59:59","level":3},"guard_leader":null,"medal":{"color":1725515,"color_border":6809855,"color_end":5414290,"color_start":1725515,"guard_icon":"https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png","guard_level":3,"honor_icon":"","id":0,"is_light":1,"level":23,"name":"睡叭","ruid":21500070,"score":50007380,"typ":0},"title":null,"uhead_frame":null,"uid":102076113,"wealth":null},"uname":"孤陌成影","uname_color":""}}
                JSONObject userlikeJson = contentJson.getJSONObject("data");
                //用户名
                String uname = userlikeJson.getStr("uname");
                //点赞内容
                String likeText = userlikeJson.getStr("like_text");
                //点赞图标地址
                String likeIconUrl = userlikeJson.getStr("like_icon");
                System.out.println("用户点赞："+uname+">>"+likeText);
            }else if ("INTERACT_WORD".equals(cmd)){
                //用户进入直播间 {"cmd":"INTERACT_WORD","data":{"contribution":{"grade":0},"contribution_v2":{"grade":0,"rank_type":"","text":""},"core_user_type":0,"dmscore":3,"fans_medal":{"anchor_roomid":8606940,"guard_level":0,"icon_id":0,"is_lighted":0,"medal_color":6067854,"medal_color_border":12632256,"medal_color_end":12632256,"medal_color_start":12632256,"medal_level":3,"medal_name":"R彦祖","score":1000,"special":"","target_id":3176666},"group_medal":null,"identities":[1],"is_mystery":false,"is_spread":0,"msg_type":1,"privilege_type":0,"roomid":6326729,"score":1709711446328,"spread_desc":"","spread_info":"","tail_icon":0,"tail_text":"","timestamp":1709711446,"trigger_time":1709711445269412900,"uid":402770418,"uinfo":{"base":{"face":"https://i0.hdslb.com/bfs/face/95df04aaca761e67ff8c01519ace678f8e28c68a.jpg","is_mystery":false,"name":"雨落镱宸","name_color":0,"name_color_str":"","official_info":null,"origin_info":null,"risk_ctrl_info":null},"guard":{"expired_str":"","level":0},"guard_leader":null,"medal":{"color":6067854,"color_border":12632256,"color_end":12632256,"color_start":12632256,"guard_icon":"","guard_level":0,"honor_icon":"","id":0,"is_light":0,"level":3,"name":"R彦祖","ruid":3176666,"score":1000,"typ":0},"title":null,"uhead_frame":null,"uid":402770418,"wealth":{"dm_icon_key":"","level":0}},"uname":"雨落镱宸","uname_color":""}}
                JSONObject enterLiveJson = contentJson.getJSONObject("data");
                //用户名
                String uname = enterLiveJson.getStr("uname");
                System.out.println(uname+"进入了直播间");
            }else if ("SEND_GIFT".equals(cmd)){
                //送礼物 {"cmd":"SEND_GIFT","data":{"action":"投喂","bag_gift":null,"batch_combo_id":"","batch_combo_send":null,"beatId":"","biz_source":"live","blind_gift":null,"broadcast_id":0,"coin_type":"silver","combo_resources_id":1,"combo_send":null,"combo_stay_time":6,"combo_total_coin":0,"crit_prob":0,"demarcation":1,"discount_price":0,"dmscore":165,"draw":0,"effect":0,"effect_block":1,"face":"https://i0.hdslb.com/bfs/face/d3f9a47d11c4e47628c03fb169032e46caba3758.jpg","face_effect_id":0,"face_effect_type":0,"float_sc_resource_id":0,"giftId":1,"giftName":"辣条","giftType":5,"gift_tag":[],"gold":0,"group_medal":null,"guard_level":0,"is_first":true,"is_join_receiver":false,"is_naming":false,"is_special_batch":0,"magnification":1,"medal_info":{"anchor_roomid":0,"anchor_uname":"","guard_level":0,"icon_id":0,"is_lighted":0,"medal_color":0,"medal_color_border":0,"medal_color_end":0,"medal_color_start":0,"medal_level":0,"medal_name":"","special":"","target_id":0},"name_color":"","num":300,"original_gift_name":"","price":100,"rcost":3528144,"receive_user_info":{"uid":21500070,"uname":"s1eeepy_"},"receiver_uinfo":{"base":{"face":"https://i0.hdslb.com/bfs/face/f502d16bec54c72bb837587c41e4d40d560e80e0.jpg","is_mystery":false,"name":"s1eeepy_","name_color":0,"name_color_str":"","official_info":{"desc":"","role":0,"title":"","type":-1},"origin_info":{"face":"https://i0.hdslb.com/bfs/face/f502d16bec54c72bb837587c41e4d40d560e80e0.jpg","name":"s1eeepy_"},"risk_ctrl_info":{"face":"https://i0.hdslb.com/bfs/face/f502d16bec54c72bb837587c41e4d40d560e80e0.jpg","name":"s1eeepy_"}},"guard":null,"guard_leader":null,"medal":null,"title":null,"uhead_frame":null,"uid":21500070,"wealth":null},"remain":0,"rnd":"4486035679008056320","send_master":null,"sender_uinfo":{"base":{"face":"https://i0.hdslb.com/bfs/face/d3f9a47d11c4e47628c03fb169032e46caba3758.jpg","is_mystery":false,"name":"EDG有个运营兜兜","name_color":0,"name_color_str":"","official_info":{"desc":"","role":0,"title":"","type":-1},"origin_info":{"face":"https://i0.hdslb.com/bfs/face/d3f9a47d11c4e47628c03fb169032e46caba3758.jpg","name":"EDG有个运营兜兜"},"risk_ctrl_info":{"face":"https://i0.hdslb.com/bfs/face/d3f9a47d11c4e47628c03fb169032e46caba3758.jpg","name":"EDG有个运营兜兜"}},"guard":null,"guard_leader":null,"medal":null,"title":null,"uhead_frame":null,"uid":408432498,"wealth":null},"silver":0,"super":0,"super_batch_gift_num":0,"super_gift_num":0,"svga_block":0,"switch":true,"tag_image":"","tid":"4486035679008056320","timestamp":1710498683,"top_list":null,"total_coin":30000,"uid":408432498,"uname":"EDG有个运营兜兜","wealth_level":24},"msg_id":"11505397104389120:10:1000","p_is_ack":true,"p_msg_type":1,"send_time":1710498683437}
                JSONObject sendGiftJson = contentJson.getJSONObject("data");
                //行为（投喂）
                String action = sendGiftJson.getStr("action");
                //礼物图标地址
                String face = sendGiftJson.getStr("face");
                //礼物名称
                String giftName = sendGiftJson.getStr("giftName");
                //礼物数量 int
                String num = sendGiftJson.getStr("num");
                //用户名
                String uname = sendGiftJson.getStr("uname");
                System.out.println(uname+action+giftName+"*"+num);
            }
        }
        //只存在ZIP包解压时才有的情况
        //如果byteBuffer游标 小于 byteBuffer大小，那就证明还有数据
        if(byteBuffer.position() < byteBuffer.limit()){
            unpack(byteBuffer);
        }
    }


}
